/*
Copyright (C) 1997-2008 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )

http://www.zsnes.com
http://sourceforge.net/projects/zsnes
https://zsnes.bountysource.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifdef __UNIXSDL__
#include "../gblhdr.h"
#else
#include <math.h>
#include <stdlib.h>
#endif

#include "c4proc.h"

#ifdef PI
#undef PI
#endif
#define PI 3.1415926535897932384626433832795
#define Cos(a) ((double) CosTable[a])
#define Sin(a) ((double) SinTable[a])
#define Tan(a) (CosTable[a]?((((int)SinTable[a])<<16)/CosTable[a]):(int)0x80000000)

short SinTable[512] = {
         0,    402,    804,   1206,   1607,   2009,   2410,   2811,
      3211,   3611,   4011,   4409,   4808,   5205,   5602,   5997,
      6392,   6786,   7179,   7571,   7961,   8351,   8739,   9126,
      9512,   9896,  10278,  10659,  11039,  11416,  11793,  12167,
     12539,  12910,  13278,  13645,  14010,  14372,  14732,  15090,
     15446,  15800,  16151,  16499,  16846,  17189,  17530,  17869,
     18204,  18537,  18868,  19195,  19519,  19841,  20159,  20475,
     20787,  21097,  21403,  21706,  22005,  22301,  22594,  22884,
     23170,  23453,  23732,  24007,  24279,  24547,  24812,  25073,
     25330,  25583,  25832,  26077,  26319,  26557,  26790,  27020,
     27245,  27466,  27684,  27897,  28106,  28310,  28511,  28707,
     28898,  29086,  29269,  29447,  29621,  29791,  29956,  30117,
     30273,  30425,  30572,  30714,  30852,  30985,  31114,  31237,
     31357,  31471,  31581,  31685,  31785,  31881,  31971,  32057,
     32138,  32214,  32285,  32351,  32413,  32469,  32521,  32568,
     32610,  32647,  32679,  32706,  32728,  32745,  32758,  32765,
     32767,  32765,  32758,  32745,  32728,  32706,  32679,  32647,
     32610,  32568,  32521,  32469,  32413,  32351,  32285,  32214,
     32138,  32057,  31971,  31881,  31785,  31685,  31581,  31471,
     31357,  31237,  31114,  30985,  30852,  30714,  30572,  30425,
     30273,  30117,  29956,  29791,  29621,  29447,  29269,  29086,
     28898,  28707,  28511,  28310,  28106,  27897,  27684,  27466,
     27245,  27020,  26790,  26557,  26319,  26077,  25832,  25583,
     25330,  25073,  24812,  24547,  24279,  24007,  23732,  23453,
     23170,  22884,  22594,  22301,  22005,  21706,  21403,  21097,
     20787,  20475,  20159,  19841,  19519,  19195,  18868,  18537,
     18204,  17869,  17530,  17189,  16846,  16499,  16151,  15800,
     15446,  15090,  14732,  14372,  14010,  13645,  13278,  12910,
     12539,  12167,  11793,  11416,  11039,  10659,  10278,   9896,
      9512,   9126,   8739,   8351,   7961,   7571,   7179,   6786,
      6392,   5997,   5602,   5205,   4808,   4409,   4011,   3611,
      3211,   2811,   2410,   2009,   1607,   1206,    804,    402,
         0,   -402,   -804,  -1206,  -1607,  -2009,  -2410,  -2811,
     -3211,  -3611,  -4011,  -4409,  -4808,  -5205,  -5602,  -5997,
     -6392,  -6786,  -7179,  -7571,  -7961,  -8351,  -8739,  -9126,
     -9512,  -9896, -10278, -10659, -11039, -11416, -11793, -12167,
    -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
    -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
    -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
    -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
    -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
    -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
    -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
    -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
    -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
    -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
    -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
    -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
    -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
    -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
    -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
    -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
    -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
    -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
    -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
    -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
    -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
    -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
    -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
    -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
    -12539, -12167, -11793, -11416, -11039, -10659, -10278,  -9896,
     -9512,  -9126,  -8739,  -8351,  -7961,  -7571,  -7179,  -6786,
     -6392,  -5997,  -5602,  -5205,  -4808,  -4409,  -4011,  -3611,
     -3211,  -2811,  -2410,  -2009,  -1607,  -1206,   -804,   -402
};

short CosTable[512] = {
     32767,  32765,  32758,  32745,  32728,  32706,  32679,  32647,
     32610,  32568,  32521,  32469,  32413,  32351,  32285,  32214,
     32138,  32057,  31971,  31881,  31785,  31685,  31581,  31471,
     31357,  31237,  31114,  30985,  30852,  30714,  30572,  30425,
     30273,  30117,  29956,  29791,  29621,  29447,  29269,  29086,
     28898,  28707,  28511,  28310,  28106,  27897,  27684,  27466,
     27245,  27020,  26790,  26557,  26319,  26077,  25832,  25583,
     25330,  25073,  24812,  24547,  24279,  24007,  23732,  23453,
     23170,  22884,  22594,  22301,  22005,  21706,  21403,  21097,
     20787,  20475,  20159,  19841,  19519,  19195,  18868,  18537,
     18204,  17869,  17530,  17189,  16846,  16499,  16151,  15800,
     15446,  15090,  14732,  14372,  14010,  13645,  13278,  12910,
     12539,  12167,  11793,  11416,  11039,  10659,  10278,   9896,
      9512,   9126,   8739,   8351,   7961,   7571,   7179,   6786,
      6392,   5997,   5602,   5205,   4808,   4409,   4011,   3611,
      3211,   2811,   2410,   2009,   1607,   1206,    804,    402,
         0,   -402,   -804,  -1206,  -1607,  -2009,  -2410,  -2811,
     -3211,  -3611,  -4011,  -4409,  -4808,  -5205,  -5602,  -5997,
     -6392,  -6786,  -7179,  -7571,  -7961,  -8351,  -8739,  -9126,
     -9512,  -9896, -10278, -10659, -11039, -11416, -11793, -12167,
    -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
    -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
    -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
    -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
    -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
    -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
    -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
    -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
    -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
    -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
    -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
    -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
    -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
    -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
    -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
    -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
    -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
    -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
    -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
    -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
    -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
    -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
    -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
    -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
    -12539, -12167, -11793, -11416, -11039, -10659, -10278,  -9896,
     -9512,  -9126,  -8739,  -8351,  -7961,  -7571,  -7179,  -6786,
     -6392,  -5997,  -5602,  -5205,  -4808,  -4409,  -4011,  -3611,
     -3211,  -2811,  -2410,  -2009,  -1607,  -1206,   -804,   -402,
         0,    402,    804,   1206,   1607,   2009,   2410,   2811,
      3211,   3611,   4011,   4409,   4808,   5205,   5602,   5997,
      6392,   6786,   7179,   7571,   7961,   8351,   8739,   9126,
      9512,   9896,  10278,  10659,  11039,  11416,  11793,  12167,
     12539,  12910,  13278,  13645,  14010,  14372,  14732,  15090,
     15446,  15800,  16151,  16499,  16846,  17189,  17530,  17869,
     18204,  18537,  18868,  19195,  19519,  19841,  20159,  20475,
     20787,  21097,  21403,  21706,  22005,  22301,  22594,  22884,
     23170,  23453,  23732,  24007,  24279,  24547,  24812,  25073,
     25330,  25583,  25832,  26077,  26319,  26557,  26790,  27020,
     27245,  27466,  27684,  27897,  28106,  28310,  28511,  28707,
     28898,  29086,  29269,  29447,  29621,  29791,  29956,  30117,
     30273,  30425,  30572,  30714,  30852,  30985,  31114,  31237,
     31357,  31471,  31581,  31685,  31785,  31881,  31971,  32057,
     32138,  32214,  32285,  32351,  32413,  32469,  32521,  32568,
     32610,  32647,  32679,  32706,  32728,  32745,  32758,  32765
};

short C4WFXVal;
short C4WFYVal;
short C4WFZVal;
short C4WFX2Val;
short C4WFY2Val;
short C4WFDist;
short C4WFScale;
double tanval;
double c4x,c4y,c4z;
double c4x2,c4y2,c4z2;

void C4TransfWireFrame()
{
  c4x=(double)C4WFXVal;
  c4y=(double)C4WFYVal;
  c4z=(double)C4WFZVal-0x95;

  // Rotate X
  tanval=-(double)C4WFX2Val*PI*2/128;
  c4y2=c4y*cos(tanval)-c4z*sin(tanval);
  c4z2=c4y*sin(tanval)+c4z*cos(tanval);

  // Rotate Y
  tanval=-(double)C4WFY2Val*PI*2/128;
  c4x2=c4x*cos(tanval)+c4z2*sin(tanval);
  c4z=c4x*-sin(tanval)+c4z2*cos(tanval);

  // Rotate Z
  tanval=-(double)C4WFDist*PI*2/128;
  c4x=c4x2*cos(tanval)-c4y2*sin(tanval);
  c4y=c4x2*sin(tanval)+c4y2*cos(tanval);

  // Scale
  C4WFXVal=(short)(c4x*C4WFScale/(0x90*(c4z+0x95))*0x95);
  C4WFYVal=(short)(c4y*C4WFScale/(0x90*(c4z+0x95))*0x95);
}

void C4TransfWireFrame2()
{
  c4x=(double)C4WFXVal;
  c4y=(double)C4WFYVal;
  c4z=(double)C4WFZVal;

  // Rotate X
  tanval=-(double)C4WFX2Val*PI*2/128;
  c4y2=c4y*cos(tanval)-c4z*sin(tanval);
  c4z2=c4y*sin(tanval)+c4z*cos(tanval);

  // Rotate Y
  tanval=-(double)C4WFY2Val*PI*2/128;
  c4x2=c4x*cos(tanval)+c4z2*sin(tanval);
  c4z=c4x*-sin(tanval)+c4z2*cos(tanval);

  // Rotate Z
  tanval=-(double)C4WFDist*PI*2/128;
  c4x=c4x2*cos(tanval)-c4y2*sin(tanval);
  c4y=c4x2*sin(tanval)+c4y2*cos(tanval);

  // Scale
  C4WFXVal=(short)(c4x*C4WFScale/0x100);
  C4WFYVal=(short)(c4y*C4WFScale/0x100);
}

void C4CalcWireFrame()
{
  C4WFXVal=C4WFX2Val-C4WFXVal;
  C4WFYVal=C4WFY2Val-C4WFYVal;
  if (abs(C4WFXVal)>abs(C4WFYVal)){
    C4WFDist=abs(C4WFXVal)+1;
    C4WFYVal=(short)((256*(long)C4WFYVal)/abs(C4WFXVal));
    if (C4WFXVal<0) C4WFXVal=-256;
    else C4WFXVal=256;
  }
  else
  if (C4WFYVal!=0) {
    C4WFDist=abs(C4WFYVal)+1;
    C4WFXVal=(short)((256*(long)C4WFXVal)/abs(C4WFYVal));
    if (C4WFYVal<0) C4WFYVal=-256;
    else C4WFYVal=256;
  }
  else C4WFDist=0;
}

short C41FXVal;
short C41FYVal;
short C41FAngleRes;
short C41FDist;
short C41FDistVal;

void C4Op1F()
{
  if (C41FXVal == 0) {
    if (C41FYVal>0) C41FAngleRes=0x80;
      else C41FAngleRes=0x180;
  }
  else {
    tanval = ((double)C41FYVal)/((double)C41FXVal);
    C41FAngleRes=(short)(atan(tanval)/(PI*2)*512);
    C41FAngleRes=C41FAngleRes;
    if (C41FXVal<0) C41FAngleRes+=0x100;
    C41FAngleRes&=0x1FF;
  }
}

void C4Op15()
{
  tanval=sqrt(((double)C41FYVal)*((double)C41FYVal)+((double)C41FXVal)*
    ((double)C41FXVal));
  C41FDist=(short)tanval;
}

void C4Op0D()
{
  tanval=sqrt(((double)C41FYVal)*((double)C41FYVal)+((double)C41FXVal)*
    ((double)C41FXVal));
  tanval=(double)C41FDistVal/tanval;
  C41FYVal=(short)(((double)C41FYVal*tanval)*0.99);
  C41FXVal=(short)(((double)C41FXVal*tanval)*0.98);
}

#define READ_WORD(s) (*(unsigned short *) (s))
void C4Op22()
{
  short angle1 = READ_WORD(C4Ram+0x1f8c) & 0x1ff;
  short angle2 = READ_WORD(C4Ram+0x1f8f) & 0x1ff;
  int tan1 = Tan(angle1);
  int tan2 = Tan(angle2);
  short y = READ_WORD(C4Ram+0x1f83) - READ_WORD(C4Ram+0x1f89);
  short left, right;

  int j;
  for (j = 0; j < 225; j++, y++)
  {
    if (y >= 0)
    {
      left = (((int)tan1*y) >> 16) - READ_WORD(C4Ram+0x1f80) + READ_WORD(C4Ram+0x1f86);
      right = (((int)tan2*y) >> 16) - READ_WORD(C4Ram+0x1f80) + READ_WORD(C4Ram+0x1f86) + READ_WORD(C4Ram+0x1f93);

      if(left<0 && right<0)
      {
        left = 1;
        right = 0;
      }
      else if (left < 0)
      {
        left = 0;
      }
      else if (right < 0)
      {
        right = 0;
      }
      if (left > 255 && right > 255)
      {
        left = 255;
        right = 254;
      }
      else if (left > 255)
      {
        left = 255;
      }
      else if (right > 255)
      {
        right = 255;
      }
    }
    else
    {
      left = 1;
      right = 0;
    }
    C4Ram[j+0x800] = (unsigned char)left;
    C4Ram[j+0x900] = (unsigned char)right;
  }
}
